
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.StringTokenizer;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;


/** * Servlet implementation class LoginServlet */ 
public class searchservlet extends HttpServlet { 
	
	SimpleCache<String> cache = new SimpleCache<String>();
	int i=1;int j=1;int k=1;
	String word;
	String url; String tfidf;
	String[][] tfidfarr;
	 String[][] urlsarr;
	 List[] lists;
	 HashMap<String,String> amap;
	
	public void doGet(HttpServletRequest request, HttpServletResponse response) 
			throws ServletException, java.io.IOException {
		doPost(request, response);
	}
	
public void doPost(HttpServletRequest request, HttpServletResponse response) 
throws ServletException, java.io.IOException {

	String uinput = request.getParameter("username");
	StringTokenizer stz = new StringTokenizer(uinput, " ");
	String[] arr= new String[stz.countTokens()];
	int temp=0;
	long timebefore = System.currentTimeMillis();
	 
	System.out.println("CountTokens: "+stz.countTokens());
	int tokens = stz.countTokens();
	
	while(stz.hasMoreTokens()){
		arr[temp++]= stz.nextToken();
		System.out.println("intialialized array");
	}

	lists = new List[tokens];
	System.out.println("content is: "+arr[0]);
	
	

	//hit the cache
	for(int i=0;i<tokens;i++){
	lists[i]=cache.get(arr[i]);
	System.out.println("hitted cache");
	
	
	if(lists[i]==null){
		ArrayList<Worddata> mylist = new ArrayList<Worddata>();
		System.out.println("trying connection inside cache");
		Connection con=null;
		Statement st=null;
		ResultSet rs=null;
		
		try
		{

		Class.forName("com.mysql.jdbc.Driver").newInstance ();
		
			String name = arr[i];
		con=DriverManager.getConnection("jdbc:mysql://localhost:3306/Search","root","");
		st=con.createStatement() ;
		String query = "SELECT * FROM urldb s where word='"+name+"' ORDER BY s.tfidf DESC";
		System.out.println("hitted database with name: "+name);

		rs=st.executeQuery(query);
		
		while(rs.next())
		{
		 word=rs.getString(1);
		 url = rs.getString(2);
		 tfidf = rs.getString(3);
		System.out.println("Got the resulset");
		System.out.println(" "+word+" "+url+" "+tfidf);
		 Worddata data = new Worddata(url,tfidf);
		mylist.add(data);
		
		//System.out.println(""+word+" "+url+" "+tfidf);
		
		}
		cache.put(name, mylist);
		lists[i] = mylist;
		

		}
		catch(Exception eer)
		{
		System.out.println(eer.toString());
		}
		
	}
	System.out.println("the For Loop");
	
	}
	int max = 0;
	for(int i=0;i<tokens;i++){
		
		if(max<lists[i].size()){
			max = lists[i].size();
		}
	}
	
	tfidfarr=new String[tokens][max];
	urlsarr = new String[tokens][max];
	
	for(int i =0;i<tokens;i++){
		int j=0;
		
		for(Iterator it = lists[i].iterator(); it.hasNext();) {
			
			Worddata word=(Worddata) it.next();
			tfidfarr[i][j] = word.tfidf;
			urlsarr[i][j] = word.url;
			j = j+1;
	       
		}
	        
	    }
	System.out.println("inserted inside tfidf and urls");
	
	int total=0;
	for(int i=0;i<tokens;i++){
		total = total+lists[i].size();
	}
	 amap = new HashMap<String, String>();
	for(int i=0;i<tokens;i++){
		for(int k=0;k<tfidfarr[i].length;k++){
			if(amap.get(urlsarr[i][k])==null){
			amap.put(urlsarr[i][k],tfidfarr[i][k]);
			}else {
				Float other=Float.valueOf(amap.get(urlsarr[i][k]))+ Float.valueOf(tfidfarr[i][k]);
				String finalstring = Float.toString(other);
				amap.put(urlsarr[i][k], finalstring );
			}
		}
	}
	System.out.println("inserted inside hashmap");
	long timeafter = System.currentTimeMillis();
	
	long time = timeafter - timebefore;
	
	System.out.println("time taken is: "+time);
	
	
	
	
	//else connect to database , insert in cache and return the ouput
	

	
	HttpSession session = request.getSession(true); 
	session.setAttribute("user",amap); 
	response.sendRedirect("output.jsp");  
	
	} 

} 
/*
 * SimpleCache
 * Copyright (C) 2008 Christian Schenk
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 */




/**
 * This class provides a very simple implementation of an object cache.
 * 
 * @author Christian Schenk
 */
 class SimpleCache<T> {

	/** Objects are stored here */
	private final Map<String, List> objects;
	/** Holds custom expiration dates */
	private final Map<String, Long> expire;
	/** The default expiration date */
	private final long defaultExpire;
	/** Is used to speed up some operations */
	private final ExecutorService threads;

	/**
	 * Constructs the cache with a default expiration time for the objects of
	 * 100 seconds.
	 */
	public SimpleCache() {
		this(200);
	}

	/**
	 * Construct a cache with a custom expiration date for the objects.
	 * 
	 * @param defaultExpire
	 *            default expiration time in seconds
	 */
	public SimpleCache(final long defaultExpire) {
		this.objects = Collections.synchronizedMap(new HashMap<String, List>());
		this.expire = Collections.synchronizedMap(new HashMap<String, Long>());

		this.defaultExpire = defaultExpire;

		this.threads = Executors.newFixedThreadPool(256);
		Executors.newScheduledThreadPool(2).scheduleWithFixedDelay(this.removeExpired(), this.defaultExpire / 2, this.defaultExpire, TimeUnit.SECONDS);
	}

	/**
	 * This Runnable removes expired objects.
	 */
	private final Runnable removeExpired() {
		return new Runnable() {
			public void run() {
				for (final String name : expire.keySet()) {
					if (System.currentTimeMillis() > expire.get(name)) {
						threads.execute(createRemoveRunnable(name));
					}
				}
			}
		};
	}

	/**
	 * Returns a runnable that removes a specific object from the cache.
	 * 
	 * @param name
	 *            the name of the object
	 */
	private final Runnable createRemoveRunnable(final String name) {
		return new Runnable() {
			public void run() {
				objects.remove(name);
				expire.remove(name);
			}
		};
	}

	/**
	 * Returns the default expiration time for the objects in the cache.
	 * 
	 * @return default expiration time in seconds
	 */
	public long getExpire() {
		return this.defaultExpire;
	}

	/**
	 * Put an object into the cache.
	 * 
	 * @param name
	 *            the object will be referenced with this name in the cache
	 * @param obj
	 *            the object
	 */
	public void put(final String name, final List obj) {
		this.put(name, obj, this.defaultExpire);
	}

	/**
	 * Put an object into the cache with a custom expiration date.
	 * 
	 * @param name
	 *            the object will be referenced with this name in the cache
	 * @param obj
	 *            the object
	 * @param expire
	 *            custom expiration time in seconds
	 */
	public void put(final String name, final List obj, final long expireTime) {
		
		this.objects.put(name, obj);
		this.expire.put(name, System.currentTimeMillis() + expireTime * 1000);
	}

	/**
	 * Returns an object from the cache.
	 * 
	 * @param name
	 *            the name of the object you'd like to get
	 * @param type
	 *            the type of the object you'd like to get
	 * @return the object for the given name and type
	 */
	public List get(final String name) {
		final Long expireTime = this.expire.get(name);
		if (expireTime == null) return null;
		if (System.currentTimeMillis() > expireTime) {
			this.threads.execute(this.createRemoveRunnable(name));
			return null;
		}
		return this.objects.get(name);
	}

	/**
	 * Convenience method.
	 */
	/*@SuppressWarnings("unchecked")
	public <R extends T> R get(final String name, final Class<R> type) {
		return (R) this.get(name);
	} */
}
  class Worddata {
		String url;
		String tfidf;
		
		public Worddata(String a,String b){
			url= a;
			tfidf = b;
		}

	}
